use std::fs;

use anyhow::anyhow;
use clap::Args;
use fudata::db;

use log::debug;
use log::error;
use log::info;
use tokio::select;

use anyhow::Result;

use crate::cli::cnf::LOGO;
use crate::cli::commands::register_ctrl_c;
use crate::cli::commands::wait_until_next_scheduled_time;
use crate::cli::commands::CommandConfig;
use crate::todo::worker_his;
use crate::todo::MAX_WORKERS;

#[derive(Args, Debug)]
pub struct HisCommandArguments {
    #[arg(
        help = "settings to craw securities",
        short = 's',
        long = "settings",
        default_value = "./config.toml"
    )]
    /// settings in toml format, e.g. config.toml
    pub settings: String,
}
pub async fn init(HisCommandArguments { settings, .. }: HisCommandArguments) -> Result<()> {
    let dbrs = db::init().await;
    match dbrs {
        Ok(_) => {}
        Err(e) => {
            return Err(anyhow!(e));
        }
    }

    // Read the contents of the config file
    let config_str = fs
        ::read_to_string(settings.as_str())
        .expect(format!("Unable to read settings file: {}", &settings).as_str());

    // Parse the TOML content into a Value
    let config: toml::Value = config_str
        .parse()
        .expect(format!("Unable to parse TOML file: {}", &settings).as_str());

    // Access DB settings from the parsed TOML value
    let command_config = CommandConfig::from_toml(&config)?;

    debug!("(start::init) got command_config {:?}", command_config);

    info!("Starting fuda his: crawle history data...");

    debug!("(his::init) arguments: kline_his_max_days= {}", command_config.kline_his_max_days);

    // Listen for Ctrl-C signal
    let shutdown_rx_arc = register_ctrl_c();
    let his_injector = worker_his::start_worker_pool(MAX_WORKERS);
    loop {
        // Wrap the receiver in a cloneable Arc<Mutex<_>> to allow concurrent access
        let mut shutdown_rx_locked = shutdown_rx_arc.lock().await;

        select!(
            _ = shutdown_rx_locked.recv()  => {
                info!("Shutting down from signal handler");
                break;
            }
            
            // second,minute,hour,day,month,weekday
            _logo_time = wait_until_next_scheduled_time("0 0/30 * * * *" ,"_logo_time")=>{
                println!("{}", LOGO );
            }  
                      
            // second,minute,hour,day,month,weekday
            gen_todos_next_time = wait_until_next_scheduled_time(command_config.gen_todos_next_time.as_str() ,"gen_todos_next_time")=>{
                info!("\n scheduled gen_todos_next_time: {:?} ", gen_todos_next_time );
                let _ = worker_his::generate_crawl_todos(command_config.kline_his_max_days).await;
            }

            // second,minute,hour,day,month,weekday
            crawl_next_time = wait_until_next_scheduled_time(command_config.crawl_next_time.as_str(),"crawl_next_time" )=>{
                let rs = worker_his::get_oldest_crawl_todos().await;
                match rs{
                    Ok(todos) => {
                        info!("\n scheduled crawl_next_time: {:?} todos.len()= {}", crawl_next_time, todos.len());
                        for todo in todos{
                            let _ = his_injector.push(todo);
                        }
                    },
                    Err(e) => error!("(crawl::get_oldest_crawl_todos){:?}",e),
                }
            }
        );
    }
    // All ok
    Ok(())
}
